home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Chans / fax / dexNet200 / dexnet_intf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  11.6 KB  |  480 lines

  1. /* dexnet_intf.c: interfcae routines */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/fax/dexNet200/RCS/dexnet_intf.c,v 6.0 1991/12/18 20:08:53 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Chans/fax/dexNet200/RCS/dexnet_intf.c,v 6.0 1991/12/18 20:08:53 jpo Rel $
  9.  *
  10.  * $Log: dexnet_intf.c,v $
  11.  * Revision 6.0  1991/12/18  20:08:53  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15.  
  16. /* Interface to the Dexnet 200 Fax Modem */
  17.  
  18. #include    "util.h"
  19. #include    "retcode.h"
  20. #include    "adr.h"
  21. #include    "qmgr.h"
  22. #include     <isode/cmd_srch.h>
  23. #include     "tb_bpt88.h"
  24. #include    "IOB-types.h"
  25. #include    "MTA-types.h"
  26. #include    "or.h"
  27. #include     <varargs.h>
  28. #include    <sys/termios.h>
  29. #include    <sys/stat.h>
  30. #include    "../faxgeneric.h"
  31. #include     "dexnet.h"
  32.  
  33. #define DEM(faxctl) ((DexModem *)((faxctl)->softc))
  34.  
  35. extern CHAN    *mychan;
  36. static int    numPages;
  37.  
  38. /* 
  39.  *    Open dexNet device and initialize
  40.  *    Return OK or NOTOK
  41.  */
  42. dexOpen(faxctl)
  43. FaxCtlr        *faxctl;
  44. {
  45.     DexModem    *dem = DEM(faxctl);
  46.     int    ret;
  47.  
  48.     ret = openDexModem(dem);
  49.     if (ret != OK) {
  50.         PP_LOG(LLOG_EXCEPTIONS, ("dexOpen: %s", dem->errBuf));
  51.         strcpy(faxctl->errBuf, "Can't open fax device");
  52.         return(ret);
  53.     }
  54.     return OK;
  55. }
  56.  
  57. /* close dexNet */
  58. dexClose(faxctl)
  59. FaxCtlr        *faxctl;
  60. {
  61.     DexModem    *dem = DEM(faxctl);
  62.     closeDexModem(dem);
  63. }
  64.  
  65. /*
  66.  *    Copy the phone number from src to dst. Return the address of the next
  67.  *    unused byte in dst. Filter src so as to only copy the following
  68.  *    characters:
  69.  *        0-9, comma (indicates pause), W (indicates wait for dialtone)
  70.  *        P is changed to comma
  71.  *        All other characters are ignored.
  72.  */
  73. static char *
  74. copyPhoneNumber(src, dst)
  75. char    *src, *dst;
  76. {
  77.     for (; *src; src++) {
  78.         if (isdigit(*src) || (*src == ',') || (*src == 'W'))
  79.             *dst++ = *src;
  80.         else if (*src == 'P')
  81.             *dst++ = ',';
  82.     }
  83.     return(dst);
  84. }
  85.  
  86.  
  87. #define FAX_TELNOSIZE    28
  88.  
  89. static int localCall = 7;    
  90. static int longDistance = 10;
  91.  
  92. /*
  93.  *    Normalize the phone number. In general, copy the phone number 'from' 
  94.  *    into 'to', skipping "phone" whitespace (see macro isPhoneWhite).
  95.  *
  96.  *    Add prefix for local access, long distance and international calls.
  97.  *    Disallow long distance and international calls if necessary.
  98.  *
  99.  *    Return OK or NOTOK and set faxctl->errBuf
  100.  *
  101.  *    NOTE: this is completely USA-centric
  102.  */
  103. static int convertPhoneNumber(faxctl, from, to)
  104. FaxCtlr    *faxctl;
  105. char    *from, *to;
  106. {
  107.     char    *ifrom = from, *ito = to;
  108.     DexModem    *dem = DEM(faxctl);
  109.     int        digits = 0;
  110.  
  111.     /* count the actual number of digits */
  112.     for (;*ifrom;ifrom++)
  113.         if (isdigit(*ifrom))
  114.             digits++;
  115.     
  116.     if (digits < localCall) {
  117.         ;    /* do nothing */
  118.     } else if (digits == localCall) {
  119.         /* add local access if defined */
  120.         if (dem->localPrefix)
  121.             ito = copyPhoneNumber(dem->localPrefix, ito);
  122.     } else if (digits == longDistance) {
  123.         if (dem->noLongDistance) {
  124.             sprintf(faxctl->errBuf, "Long distance calls not allowed");
  125.             return(NOTOK);
  126.         } else if (dem->longdPrefix)
  127.             ito = copyPhoneNumber(dem->longdPrefix, ito);
  128.     } else if (digits > longDistance) {
  129.         char    *plus = index(from, '+');
  130.         if (!plus) {
  131.             sprintf(faxctl->errBuf, "International call not flagged with +");
  132.             return(NOTOK);
  133.         }
  134.         if (dem->noInternational) {
  135.             sprintf(faxctl->errBuf, "International calls not allowed");
  136.             return(NOTOK);
  137.         }
  138.         if (dem->intlPrefix)
  139.             ito = copyPhoneNumber(dem->intlPrefix, ito);
  140.     } else {
  141.         sprintf(faxctl->errBuf, "Invalid telephone number with %d digits", digits);
  142.         return(NOTOK);
  143.     }
  144.  
  145.     ito = copyPhoneNumber(from, ito);
  146.     *ito = '\0';
  147.  
  148.     return OK;
  149. }
  150.  
  151. /*
  152.  *    Initialize for transmission 
  153.  *    Returns: PP return code
  154.  */
  155. dexInitXmit(faxctl)
  156. FaxCtlr        *faxctl;
  157. {
  158.     DexModem    *dem = DEM(faxctl);
  159.     char    now[30], telno[FAX_TELNOSIZE];
  160.     char    *date, *tim;
  161.     time_t  clock;
  162.     int        ret = RP_BOK;
  163.  
  164.     faxctl->qmgrErrCode = int_Qmgr_status_mtaFailure;
  165.     numPages = 0;
  166.  
  167.     if (convertPhoneNumber(faxctl, faxctl->telno, telno) != OK) {
  168.         faxctl->qmgrErrCode = int_Qmgr_status_negativeDR;
  169.         PP_LOG(LLOG_EXCEPTIONS,
  170.                ("%s", faxctl->errBuf));
  171.         return(RP_MECH);
  172.     }
  173.  
  174.     PP_TRACE(("Dialing %s", telno));
  175.     
  176.     /* currently setup at 19.2K */
  177.     if (setupDexModem(dem, 1) != OK) {
  178.         PP_LOG(LLOG_EXCEPTIONS, ("dexInitXmit: setup %s", dem->errBuf));
  179.         strcpy(faxctl->errBuf, "Can't setup fax device");
  180.         return(RP_MECH);
  181.     }
  182.  
  183.     time(&clock);
  184.     strcpy(now, ctime(&clock));
  185.     date = now;
  186.     date[10] = (char)0;
  187.     tim = &now[11];
  188.     tim[8] = (char)0;
  189.  
  190.     if (dialDexModem(dem, telno, date, tim, dem->tti) != OK) {
  191.         PP_LOG(LLOG_EXCEPTIONS, ("dexOpen: dial %s", dem->errBuf));
  192.         strcpy(faxctl->errBuf, "Can't dial remote fax device");
  193.         ret = RP_MECH;
  194.     }
  195.     return(ret);
  196. }
  197.  
  198. /* 
  199.  *    Abort the call. It would be nice to just send a RESET to the modem,
  200.  *    but it may be in la-la land with CTS off, so the only sure-fire way
  201.  *     to reset is to use the hardware reset (drop DTR for a bit). Arrgh!
  202.  */
  203. dexAbort(faxctl)
  204. FaxCtlr        *faxctl;
  205. {
  206.     DexModem    *dem = DEM(faxctl);
  207.      hardResetDexModem(dem);
  208. }
  209.  
  210. /*
  211.  *    Terminate transmission to remote fax
  212.  *    Returns: OK or NOTOK
  213.  */
  214. dexTermXmit(faxctl)
  215. FaxCtlr        *faxctl;
  216. {
  217.     DexModem    *dem = DEM(faxctl);
  218.     int            ret = OK;
  219.  
  220.     if ((ret = eomDexModem(dem)) != OK) {
  221.         /* based on actual error, either retry or abort */
  222.         if (dem->msgCode == dexNotAFax) {
  223.             faxctl->qmgrErrCode = int_Qmgr_status_negativeDR;
  224.         } else {
  225.             faxctl->qmgrErrCode = int_Qmgr_status_messageFailure;
  226.         }
  227.         PP_LOG(LLOG_EXCEPTIONS, ("dexTermXmit: dial %s", dem->msgBuf));
  228.         strcpy(faxctl->errBuf, dem->msgBuf);
  229.         ret = NOTOK;
  230.     }
  231.     return(ret);
  232. }
  233.  
  234. /*
  235.  *    Set/Test the G3 Parameters
  236.  */
  237.  
  238. dexSetParams(faxctl, params)
  239. FaxCtlr        *faxctl;
  240. struct type_IOB_G3FacsimileParameters *params;
  241. {
  242.     DexModem        *dem = DEM(faxctl);
  243.  
  244.     if (params -> non__basic__parameters) {
  245.         if (bit_test(params -> non__basic__parameters,
  246.                              bit_MTA_G3FacsimileNonBasicParameters_two__dimensional) == 1) {
  247.                         PP_LOG(LLOG_EXCEPTIONS,
  248.                                ("Unable to deal with two dimensional fax"));
  249.             sprintf(faxctl->errBuf,
  250.                 "Unable to deal with two dimensional fax");
  251.                         return NOTOK;
  252.                 }
  253.  
  254.                 if (bit_test(params -> non__basic__parameters,
  255.                              bit_MTA_G3FacsimileNonBasicParameters_uncompressed) == 1) {
  256.                         PP_LOG(LLOG_EXCEPTIONS,
  257.                                ("Unable to deal with uncompressed fax"));
  258.             sprintf(faxctl->errBuf,
  259.                 "Unable to deal with uncompressed fax");
  260.                         return NOTOK;
  261.                 }
  262.                 
  263.                 if (bit_test(params -> non__basic__parameters,
  264.                              bit_MTA_G3FacsimileNonBasicParameters_fine__resolution) == 1) 
  265.             IssueData(dem, FINE_RES, "FINE_RES");
  266.  
  267.     }
  268.     return OK;
  269. }
  270.  
  271. /* set correct error code based upon dexnet errors */
  272. dexGenQmgrError(faxctl)
  273. FaxCtlr    *faxctl;
  274. {
  275.     DexModem        *dem = DEM(faxctl);
  276.     if (dem->msgBuf[0]) {
  277.         strcpy(faxctl->errBuf, dem->msgBuf);
  278.         switch (dem->msgCode) {
  279.             case dexNotAFax:
  280.                 faxctl->qmgrErrCode = int_Qmgr_status_negativeDR;
  281.                 break;
  282.             case dexNoResponse: /* no answer, retry message */
  283.             case dexBusy:
  284.             case dexDisconnect: /* dropped line */
  285.                 faxctl->qmgrErrCode = int_Qmgr_status_messageFailure;
  286.                 break;
  287.             /* all else gets MTA failure */
  288.             default:
  289.                 faxctl->qmgrErrCode = int_Qmgr_status_mtaFailure;
  290.                 break;
  291.         }
  292.     } else {
  293.         PP_LOG(LLOG_EXCEPTIONS,
  294.             ("Error sending page: %s", dem->errBuf));
  295.         strcpy(faxctl->errBuf, "Error communicating with fax modem");
  296.     }
  297. }
  298.  
  299. /*
  300.  *    Send one page of G3 fax
  301.  *    Returns: OK or NOTOK
  302.  */
  303. dexSendPage(faxctl, str, len, last)
  304. FaxCtlr        *faxctl;
  305. char        *str;        /* g3 fax data to send */
  306. int            len;        /* len of str in bytes */
  307. int            last;        /* true if last page */
  308. {
  309.     DexModem        *dem = DEM(faxctl);
  310.     unsigned char    *fuji;
  311.     int                fujiLen;
  312.     int                ret = OK;
  313.  
  314.     faxctl->qmgrErrCode = int_Qmgr_status_mtaFailure;
  315.  
  316.     if ((dem->maxPages > 0) && (numPages++ > dem->maxPages)) {
  317.         /* have exceeded page count; stop transmission */
  318.         faxctl->qmgrErrCode = int_Qmgr_status_negativeDR;
  319.         sprintf(faxctl->errBuf, "Transmission truncated: pagecount %d exceeded",
  320.             dem->maxPages);
  321.         return(NOTOK);
  322.     }
  323.  
  324.     /* 
  325.      *    Convert G3 fax to (stupidly encoded) dexNet coding.
  326.      *    conversion will add 4 bytes for every scanline. Thus
  327.      *    about 1800 scanlines * 4 < 8000
  328.      */
  329.     fuji = (unsigned char *)malloc(len + 8000);
  330.     fujiLen = fujicnvrt(str, fuji, len);
  331.     ret = sendDexModem(dem, fuji, fujiLen, /* G3 mode */0);
  332.     free(fuji);
  333.  
  334.     if (ret != OK) {
  335.         dexGenQmgrError(faxctl);
  336.     }
  337.     return(ret);
  338. }
  339.  
  340. /*
  341.  *    Open file and send as text to fax modem. 
  342.  *    Reads entire file into memory, converts each linefeed to carriage
  343.  *    return, linefeed. Return OK or NOTOK
  344.  */
  345. dexSendIA5File(faxctl, fileName, last)
  346. FaxCtlr        *faxctl;
  347. char        *fileName;    /* file to send */
  348. int            last;        /* true if last bodypart */
  349. {
  350.     struct stat        sbuf;
  351.     unsigned char    *buf;
  352.     int                len = 0, bufLen;
  353.     int                lines = 0;
  354.     unsigned char     *p;
  355.     int                cc;
  356.     FILE            *fp;
  357.     int                ret;
  358.     DexModem        *dem = DEM(faxctl);
  359.  
  360.     faxctl->qmgrErrCode = int_Qmgr_status_mtaFailure;
  361.  
  362.     if ((fp = fopen(fileName, "r")) == NULL) {
  363.         PP_SLOG(LLOG_EXCEPTIONS, fileName,
  364.             ("Can't open file"));
  365.         strcpy(faxctl->errBuf, "Error communicating with fax modem");
  366.         return(NOTOK);
  367.     }
  368.  
  369.     fstat(fileno(fp), &sbuf);
  370.     bufLen = sbuf.st_size*2;    /* worst case estimate */
  371.     p = buf = (unsigned char *)malloc(bufLen);
  372.     bzero(buf, bufLen);
  373.  
  374.     while (fgets(p, bufLen - len, fp) != NULL) {
  375.         cc = strlen(p);
  376.         p[cc++] = '\r';    /* add carriage return */
  377.         len += cc;
  378.         p += cc;
  379.         lines++;
  380.     }
  381.  
  382.     /* assume 66 lines per page */
  383.     if ((dem->maxPages > 0) && ((lines/66) > dem->maxPages)) {
  384.         /* exceeded page count */
  385.         faxctl->qmgrErrCode = int_Qmgr_status_negativeDR;
  386.         sprintf(faxctl->errBuf, "Attempt to send more than %d pages",
  387.             dem->maxPages);
  388.         free (buf);
  389.         return(NOTOK);
  390.     }
  391.  
  392.     ret = sendDexModem(dem, buf, len, /* textmode true */ 1);
  393.     free(buf);
  394.  
  395.     if (ret != OK) {
  396.         dexGenQmgrError(faxctl);
  397.     }
  398.     return(ret);
  399. }
  400.  
  401. /*
  402.  * parse info line arguments
  403.  *
  404.  *    out: name of device
  405.  *    tti: ng tti field
  406.  *    noLong: disallow long distance calls
  407.  *    noIntl: disallow international calls
  408.  *    localPrefix: local access prefix (i.e., outside line)
  409.  *    longPrefix: long distance access prefix
  410.  *    intlPrefix: international prefix
  411.  *    max_pages: limit number of pages sent to this value
  412.  */
  413. int dexArgParse (faxctl, key, value)
  414. FaxCtlr    *faxctl;
  415. char    *key;
  416. char    *value;
  417. {
  418.     DexModem    *dem = DEM(faxctl);
  419.  
  420.     if (lexequ(key, "out") == 0)
  421.         strcpy(dem->devName, value);
  422.     else if (lexequ(key, "tti") == 0)
  423.         strcpy(dem->tti, value);
  424.     else if (lexequ(key, "localPrefix") == 0)
  425.         dem->localPrefix = strdup(value);
  426.     else if (lexequ(key, "longPrefix") == 0)
  427.         dem->longdPrefix = strdup(value);
  428.     else if (lexequ(key, "intlPrefix") == 0)
  429.         dem->intlPrefix = strdup(value);
  430.     else if (lexequ(key, "long") == 0)
  431.         if (lexequ(value, "ok") == 0)
  432.             dem->noLongDistance = 0;
  433.         else
  434.             dem->noLongDistance = 1;
  435.     else if (lexequ(key, "intl") == 0)
  436.         if (lexequ(value, "ok") == 0)
  437.             dem->noInternational = 0;
  438.         else
  439.             dem->noInternational = 1;
  440.     else if (lexequ(key, "maxPages") == 0)
  441.         dem->maxPages = atoi(value);
  442.     else {
  443.         sprintf(faxctl->errBuf,
  444.                "Unknown info arg '%s=%s",
  445.             key, value);
  446.         return NOTOK;
  447.     }
  448.     return OK;
  449. }
  450.  
  451. /*
  452.  *    Return a fax control block
  453.  */
  454.  
  455. FaxCtlr    *init_faxctrlr()
  456. {
  457.     FaxCtlr    *faxctl;
  458.     DexModem    *dem;
  459.  
  460.     faxctl = (FaxCtlr *)malloc(sizeof(FaxCtlr));
  461.         bzero(faxctl, sizeof(FaxCtlr));
  462.  
  463.     dem = (DexModem *)malloc(sizeof(DexModem));
  464.     bzero(dem, sizeof(DexModem));
  465.     sprintf(dem->devName, "/dev/tty01"); /* default for now */
  466.     faxctl->softc = (char *) dem;
  467.  
  468.         faxctl->open = dexOpen;
  469.         faxctl->close = dexClose;
  470.         faxctl->initXmit = dexInitXmit;
  471.         faxctl->abort = dexAbort;
  472.         faxctl->termXmit = dexTermXmit;
  473.         faxctl->setG3Params = dexSetParams;
  474.         faxctl->sendPage = dexSendPage;
  475.     faxctl->setIA5Params = NULLIFP;
  476.         faxctl->sendIA5File = dexSendIA5File;
  477.     faxctl->arg_parse = dexArgParse;
  478.     return faxctl;
  479. }
  480.